package com.ybt.message.manager;

import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.log4j.Logger;
import org.jdom.Document;
import org.jdom.Element;

import com.sinosoft.midplat.common.JdomUtil;
import com.ybt.configration.IYBTConfigration;
import com.ybt.configration.YBTConfigration;
import com.ybt.configration.YBTRuntimeConfiguration;
import com.ybt.message.pack.IMessagePack;
import com.ybt.message.pack.MessagePackDecorator;
import com.ybt.message.unpack.IMessageUnpack;
import com.ybt.message.unpack.MessageUnpackDecorator;

public class PackUnpackFactory {
    private static Logger logger = Logger.getLogger(PackUnpackFactory.class);
    private static String CONFIG_DIR = "message" + File.separator
            + "packUnpack.xml";
    private Map<String, PackUnpackDefine> define;

    private volatile static PackUnpackFactory manager;

    private PackUnpackFactory() {
        define = new HashMap<String, PackUnpackDefine>();

        CONFIG_DIR = YBTConfigration.getInstance().getProperty(
                IYBTConfigration.WORKFLOW_DEPLOY_PATH)
                + File.separator + CONFIG_DIR;

        loadFromLocal();
    }

    public static PackUnpackFactory getInstance() {
        if (manager == null) {
            synchronized (PackUnpackFactory.class) {
                if (manager == null) {
                    manager = new PackUnpackFactory();
                }
            }
        }
        return manager;
    }

    /**
     * 根据渠道名称，获取解包实现.
     * 
     * @param channel
     *            渠道名称
     * @return 打包实现类对象
     */
    public IMessageUnpack createUnpackDecorator(String type, IMessageUnpack unpack, Element config) {
        // 获取渠道打包类型
        PackUnpackDefine def = define.get(type);
        if (def == null || def.unpack == null) {
            throw new RuntimeException("unsupport unpack service of type ["
                    + type + "]");
        }
        logger.debug("the unpack service mapping is [" + type + "---"
                + def.unpack + "]");
        try {
            // 初始化打包服务
            Class c = Class.forName(def.unpack);
            MessageUnpackDecorator d = (MessageUnpackDecorator) c.getConstructor(IMessageUnpack.class).newInstance(unpack);
            d.setUnpackConfig(config);
            return d;
            
        } catch (Exception e) {
            throw new RuntimeException("initialize unpack service error :"
                    + def.unpack, e);
        }
    }
    
    /**
     * 根据渠道名称，获取打包实现.
     * 
     * @param channel
     *            渠道名称
     * @return 打包实现类对象
     */
    public IMessagePack createPackDecorator(String type, IMessagePack pack, Element config) {
        // 获取渠道打包类型
        PackUnpackDefine def = define.get(type);
        if (def == null || def.pack == null) {
            throw new RuntimeException("unsupport pack service of type ["
                    + type + "]");
        }
        logger.debug("the pack service mapping is [" + type + "---"
                + def.pack + "]");
        try {
            // 初始化打包服务
            Class c = Class.forName(def.pack);
            MessagePackDecorator d = (MessagePackDecorator) c.getConstructor(IMessagePack.class).newInstance(pack);
            d.setUnpackConfig(config);
            return d;
            
        } catch (Exception e) {
            throw new RuntimeException("initialize pack service error :"
                    + def.pack, e);
        }
    }

    private void loadFromLocal() {

        File file = new File(CONFIG_DIR);
        if (!file.exists()) {
            throw new RuntimeException("can't find the configration file : "
                    + CONFIG_DIR);
        }

        try {
            InputStream in = new FileInputStream(CONFIG_DIR);
            Document doc = JdomUtil.build(in, YBTRuntimeConfiguration
                    .getInstance().getConfigFileCharset().name());

            List<Element> tasks = doc.getRootElement().getChildren();
            for (Element et : tasks) {
                String type = et.getAttributeValue("name");
                PackUnpackDefine item = new PackUnpackDefine();
                item.type = type;

                Element ep = et.getChild("pack");
                if (ep != null) {
                    String pack = ep.getText();
                    item.pack = pack;
                }
                Element eu = et.getChild("unpack");
                if (ep != null) {
                    String unpack = eu.getText();
                    item.unpack = unpack;
                }
                define.put(type, item);

                logger
                        .debug("load pack and unpack implement configration define ["
                                + type + " : " + type + "]");
            }
        } catch (Exception e) {
            throw new RuntimeException("parse configration file error : "
                    + CONFIG_DIR, e);
        }
    }

    private class PackUnpackDefine {
        String type;
        String pack;
        String unpack;
    }
}